package asteroids.engine;

import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;

import org.apache.log4j.Logger;

import asteroids.engine.ai.KeyboardPilot;
import asteroids.entity.AlienShip;
import asteroids.entity.Asteroid;
import asteroids.entity.Ship;
import asteroids.entity.equipment.MADDevice;
import asteroids.entity.weapon.LazerWeapon;
import asteroids.factory.ShapeLib;
import asteroids.factory.Shipyard;

/**
 * Classic gameplay - Asteroids are generated in waves which must be destroyed.
 * Aliens will occasionally come by and take potshots at random things.
 * 
 * @author whitecd1
 * 
 */
public class ClassicScenario extends Scenario
{
    private Logger logger = Logger.getLogger(ClassicScenario.class);

    private int waveNumber;
    // private int fieldSizeIncrement = 50;// 25;
    private int timeUntilRestart = 0;
    private int MOMENTOFSILENCE = 4 * Utils.FRAMES_PER_SECOND;

    private double fieldDensity = (2.5 / 9000) / 2;

    private boolean gameOver = false;
    private ArrayList<Ship> ships;

    private HUD hud;

    /**
     * Fully initializes the GameState; discarding any previous things
     * 
     * @param state
     */
    public void initialize(GameState state)
    {
        gameOver = false;
        waveNumber = 0;

        state.clear();

        // make ships
        // Ship ship = Shipyard.getClassicShip("Wedge", Utils.GAME_WIDTH / 2,
        // Utils.GAME_HEIGHT / 2,
        // ShapeLib.ShipType.WEDGE);
        // ((PlayerShip) ship).setAcceleration(300.0 / Utils.FRAMES_PER_SECOND
        // / Utils.FRAMES_PER_SECOND);
        // Ship ship = Shipyard.buildBroodhome("Chen", Utils.GAME_WIDTH / 2,
        // Utils.GAME_HEIGHT / 2);
        // Ship ship = Shipyard.buildTerminator("Zeep-eep", Utils.GAME_WIDTH /
        // 2,
        // Utils.GAME_HEIGHT / 2);
        // Ship ship = Shipyard.buildCruiser("Spiff", Utils.GAME_WIDTH / 2,
        // Utils.GAME_HEIGHT / 2);
        // ship.arm(new CruiseMissiles(ship));
        // ship.setSpecial(new LaunchFighters(ship));

        // Ship ship = Shipyard.buildShip("Spiff", Utils.GAME_WIDTH / 2,
        // Utils.GAME_HEIGHT / 2,
        // ShapeLib.ShipType.CRUISER);
        // Ship ship = Shipyard.buildShip("CHEN", Utils.GAME_WIDTH / 2,
        // Utils.GAME_HEIGHT / 2,
        // ShapeLib.ShipType.BROODHOME);
        // Ship ship = Shipyard.buildShip("Zeep-eep", Utils.GAME_WIDTH / 2,
        // Utils.GAME_HEIGHT / 2,
        // ShapeLib.ShipType.TERMINATOR);
        Ship ship = Shipyard.buildShip("Lord 9", Utils.GAME_WIDTH / 2, Utils.GAME_HEIGHT / 2,
                ShapeLib.ShipType.DREADNAUGHT);
        ship.arm(new LazerWeapon(ship, 2, 1, 0, false, 100));
        ship.setSpecial(new LazerWeapon(ship, 3, 10, 20, true, 350));
        // ship.equip(new RegeneratingShield(ship, 10));

        // Ship ship = new PlayerShip("Trident", Utils.GAME_WIDTH / 2,
        // Utils.GAME_HEIGHT / 2,
        // ShapeLib.TRIDENT_SHAPE, 180.0 / Utils.FRAMES_PER_SECOND, 180.0
        // / Utils.FRAMES_PER_SECOND / Utils.FRAMES_PER_SECOND, 20, 100);
        // ((PlayerShip) ship).setHardPoints(ShapeLib.TRIDENT_POINTS);
        // {
        //
        // // ship.arm(new ClassicWeapon(ship));
        // ship.arm(new ConfigurableWeapon(ship, 240d / Utils.FRAMES_PER_SECOND,
        // 1, 2,
        // Utils.FRAMES_PER_SECOND / 2, 0, false));
        // // ship.setSpecial(new LaunchFighters(ship));
        // ship.setSpecial(new ConfusionRay(ship));
        // ship.equip(new Dynamo(ship));
        // ship.modifyIntegrityBy(10);
        // }
        ship.setPilot(new KeyboardPilot());

        // Ship h = Shipyard.getClassicShip("Hourglass", Utils.GAME_WIDTH *
        // 0.25,
        // Utils.GAME_HEIGHT * 0.66, ShapeLib.ShipType.HOURGLASS);
        // Ship h = Shipyard.buildCruiser("Hank", Utils.GAME_WIDTH * 0.25,
        // Utils.GAME_HEIGHT * 0.66);
        // h.setSpecial(new ForceShield(h));
        // h.arm(new CruiseMissiles(h));
        // h.equip(new Dynamo(h));
        // h.setAffiliation("H");

        // Ship t = Shipyard.getClassicShip("Trident", Utils.GAME_WIDTH * 0.75,
        // Utils.GAME_HEIGHT * 0.66, ShapeLib.TRIDENT_SHAPE);
        // t.arm(new CruiseMissiles(t));
        // t.equip(new Dynamo(t));
        // t.setAffiliation("T");

        ships = new ArrayList<Ship>();
        ships.add(ship);
        // ships.add(h);
        // ships.add(t);

        // ship.equip(new AutoShield(ship));
        // h.equip(new AutoShield(h));
        // t.equip(new AutoShield(t));

        for( Ship s : ships )
        {
            s.grantTemporaryInvincibility();
            s.addLives(2);
        }
        state.getShipManager().addAll(ships);

        hud = new CompactHUD();
        hud.initialize(state);
    }

    @Override
    public void update(GameState state)
    {
        logger.trace("---Update---");
        if( state.getAsteroidManager().getObjects().size() == 0 ) // asteroids
                                                                  // are gone
        {
            waveNumber = waveNumber + 1;
            // int fieldSize = waveNumber * fieldSizeIncrement;

            logger.info("Starting wave " + waveNumber);

            for( Ship s : state.getShipManager().getObjects() )
            {
                s.grantTemporaryInvincibility();
            }
            Asteroid a = new Asteroid(0, 0,
                    (int) (fieldDensity * Utils.GAME_WIDTH * Utils.GAME_HEIGHT) / 2 * waveNumber);
            state.getAsteroidManager().addAll(a.fragment(15));
            ((AsteroidManager) state.getAsteroidManager()).randomizeAsteroidLocations();
        }

        if( allShipsInactive() && !gameOver ) // players are out of lives.
                                              // Bummer
        {
            logger.info("Game Over, man");
            gameOver = true;
            timeUntilRestart = MOMENTOFSILENCE;
        }

        if( gameOver )
        {
            // just count down and then restart
            if( timeUntilRestart == 0 )
            {
                restart(state);
            }
            else
            {
                timeUntilRestart -= 1;
            }
        }
        if( Math.random() < (0.05 / Utils.FRAMES_PER_SECOND) )
        {
            // create an alien ship at one side of the screen or the other with
            // random height
            AlienShip as = new AlienShip((Math.random() < 0.5) ? 0 : Utils.GAME_WIDTH,
                    Math.random() * Utils.GAME_HEIGHT);
            as.equip(new MADDevice(as, (Math.random() * ShapeLib.shipLength * 7)
                    + ShapeLib.shipLength));
            // as.equip(new Shield(as));
            // as.equip(new PointDefense(as));
            state.getShipManager().add(as);
        }
    }

    public void restart(GameState state)
    {
        logger.info("Restarting");
        initialize(state);
    }

    public boolean allShipsInactive()
    {
        boolean allInactive = true;
        for( Ship s : ships )
        {
            if( s.isActive() )
            {
                allInactive = false;
            }
        }
        return allInactive;
    }

    public void draw(Graphics g)
    {
        hud.draw(g);
        int ypos = 10;
        for( Ship s : ships )
        {
            g.drawString("" + s.getScore(), 10, ypos);
            ypos += 20;
        }
        if( gameOver && timeUntilRestart != 0 )
        {
            g.setColor(Color.WHITE);
            g.drawString("G A M E   O V E R", Utils.GAME_WIDTH / 2 - 40, Utils.GAME_HEIGHT / 2 - 10);
        }
    }

    public void erase(Graphics g)
    {
        if( gameOver && timeUntilRestart == 0 )
        {
            // g.setColor(Color.BLACK);
            // g.fillRect(0, 0, Utils.GAME_WIDTH, Utils.GAME_HEIGHT);
            // g.setColor(Color.WHITE);
            // g.drawString("G A M E   O V E R", Utils.GAME_WIDTH / 2 - 40,
            // Utils.GAME_HEIGHT / 2 - 10);
        }
    }
}
